﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.DebugViews;

namespace UtilZ.Dotnet.Ex.Model
{
#pragma warning disable 8500 // address / sizeof of managed types

    /// <summary>
    /// IQSpanZ
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [DebuggerTypeProxy(typeof(IQSequenceDebugView<>))]
    [DebuggerDisplay("Length = {Length}")]
    unsafe public ref struct IQSpanZ<T> where T : struct
    {
        /// <summary>
        /// I路指针
        /// </summary>
        public readonly T* IDataPtr;

        /// <summary>
        /// Q路指针
        /// </summary>
        public readonly T* QDataPtr;

        /// <summary>
        /// 有效数据个数
        /// </summary>
        public readonly int Length;

        /// <summary>
        /// 有效数据个数
        /// </summary>
        public readonly long LongLength;



        /// <summary>
        /// 构造函数实例化
        /// </summary>
        /// <param name="iDataPtr">I路数据指针</param>
        /// <param name="qDataPtr">Q路数据指针</param>
        /// <param name="length">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">数据长度越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ(void* iDataPtr, void* qDataPtr, int length)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

#if CORE
            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
            {
                throw new NotSupportedException($"不支持的类型\"{typeof(T)}\"");
            }
#endif

            this.IDataPtr = (T*)iDataPtr;
            this.QDataPtr = (T*)qDataPtr;
            this.Length = length;
            this.LongLength = length;
        }

        /// <summary>
        /// 构造函数实例化
        /// </summary>
        /// <param name="iDataPtr">I路数据指针</param>
        /// <param name="qDataPtr">Q路数据指针</param>
        /// <param name="length">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">数据长度越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ(void* iDataPtr, void* qDataPtr, long length)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

#if CORE
            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
            {
                throw new NotSupportedException($"不支持的类型\"{typeof(T)}\"");
            }
#endif

            this.IDataPtr = (T*)iDataPtr;
            this.QDataPtr = (T*)qDataPtr;
            if (length > int.MaxValue)
            {
                this.Length = int.MaxValue;
            }
            else
            {
                this.Length = (int)length;
            }
            this.LongLength = length;
        }



        /// <summary>
        /// 获取I路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>I路指定索引处的数据</returns>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public ref T GetI(long index)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            return ref *(this.IDataPtr + index);
        }

        /// <summary>
        /// 设置I路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="value">目标值</param>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void SetI(long index, in T value)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            *(this.IDataPtr + index) = value;
        }

        /// <summary>
        /// 获取I路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>I路指定索引处的数据</returns>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public ref T GetI(int index)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            return ref *(this.IDataPtr + index);
        }

        /// <summary>
        /// 设置I路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="value">目标值</param>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void SetI(int index, in T value)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            *(this.IDataPtr + index) = value;
        }





        /// <summary>
        /// 获取Q路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>Q路指定索引处的数据</returns>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public ref T GetQ(long index)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            return ref *(this.QDataPtr + index);
        }

        /// <summary>
        /// 设置Q路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="value">目标值</param>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void SetQ(long index, in T value)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            *(this.QDataPtr + index) = value;
        }

        /// <summary>
        /// 获取Q路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>Q路指定索引处的数据</returns>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public ref T GetQ(int index)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            return ref *(this.QDataPtr + index);
        }

        /// <summary>
        /// 设置Q路指定索引处的数据
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="value">目标值</param>
        /// <exception cref="IndexOutOfRangeException">索引越界异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void SetQ(int index, T value)
        {
            if (index < 0 || index >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index), $"索引越界,index:{index},当前数据长度:{this.LongLength}");
            }

            *(this.QDataPtr + index) = value;
        }




        /// <summary>
        /// 清除当前对象数据指针指向的内容
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Clear()
        {
            var byteLen = (nuint)(sizeof(T) * this.Length);
            NativeMemory.Clear(this.IDataPtr, byteLen);
            NativeMemory.Clear(this.QDataPtr, byteLen);
        }

        /// <summary>
        /// 用指定的值填充到当前对象数据指针指向的内容
        /// </summary>
        /// <param name="value"></param>        
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Fill(T value)
        {
            UnmanagedMemoryHelper.Fill(this.IDataPtr, this.Length, value);
            UnmanagedMemoryHelper.Fill(this.QDataPtr, this.Length, value);
        }

        /// <summary>
        /// 用指定的值填充到当前对象数据指针指向的内容
        /// </summary>
        /// <param name="startIndex">起始位置</param>
        /// <param name="count">填充个数</param>
        /// <param name="value">填充值</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Fill(long startIndex, long count, T value)
        {
            if (startIndex < 0 ||
                count < 0 ||
                startIndex + count > this.LongLength)
            {
                throw new ArgumentOutOfRangeException($"参数值无效,startIndex:{startIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            UnmanagedMemoryHelper.Fill(this.IDataPtr + startIndex, count, value);
            UnmanagedMemoryHelper.Fill(this.QDataPtr + startIndex, count, value);
        }



        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start'.
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ<T> Slice(int start)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},当前数据长度:{this.LongLength}");
            }

            return new IQSpanZ<T>(this.IDataPtr + start, this.QDataPtr + start, this.Length - start);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start'.
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ<T> Slice(long start)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},当前数据长度:{this.LongLength}");
            }

            return new IQSpanZ<T>(this.IDataPtr + start, this.QDataPtr + start, this.Length - start);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start', of given length
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <param name="length">The desired length for the slice (exclusive).</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ<T> Slice(int start, int length)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},length:{length},当前数据长度:{this.LongLength}");
            }

            if (start + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"start:{start},length:{length},当前数据长度:{this.LongLength}");
            }

            return new IQSpanZ<T>(this.IDataPtr + start, this.QDataPtr + start, length);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start', of given length
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <param name="length">The desired length for the slice (exclusive).</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public IQSpanZ<T> Slice(long start, long length)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},length:{length},当前数据长度:{this.LongLength}");
            }

            if (start + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"start:{start},length:{length},当前数据长度:{this.LongLength}");
            }

            return new IQSpanZ<T>(this.IDataPtr + start, this.QDataPtr + start, length);
        }






        /// <summary>
        /// 获取I路数据Span
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetISpan()
        {
            return new Span<T>(this.IDataPtr, this.Length);
        }

        /// <summary>
        /// 获取Q路数据Span
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan()
        {
            return new Span<T>(this.QDataPtr, this.Length);
        }


        /// <summary>
        /// 获取I路数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetISpan(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new Span<T>(this.IDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取Q路数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new Span<T>(this.QDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取I路数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetISpan(long startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new Span<T>(this.IDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取Q路数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan(long startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }


            return new Span<T>(this.QDataPtr + startIndex, length);
        }




        /// <summary>
        /// 获取I路数据SpanZ
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetISpanZ()
        {
            return new SpanZ<T>(this.IDataPtr, this.LongLength);
        }

        /// <summary>
        /// 获取Q路数据SpanZ
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetQSpanZ()
        {
            return new SpanZ<T>(this.QDataPtr, this.LongLength);
        }

        /// <summary>
        /// 获取I路数据SpanZ
        /// </summary>
        /// <param name="length">I路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetISpanZ(int length)
        {
            if (length < 0 || length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.IDataPtr, length);
        }

        /// <summary>
        /// 获取Q路数据SpanZ
        /// </summary>
        /// <param name="length">Q路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetQSpanZ(int length)
        {
            if (length < 0 || length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.QDataPtr, length);
        }

        /// <summary>
        /// 获取I路数据SpanZ
        /// </summary>
        /// <param name="length">I路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetISpanZ(long length)
        {
            if (length < 0 || length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.IDataPtr, length);
        }

        /// <summary>
        /// 获取Q路数据SpanZ
        /// </summary>
        /// <param name="length">Q路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetQSpanZ(long length)
        {
            if (length < 0 || length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.QDataPtr, length);
        }

        /// <summary>
        /// 获取I路数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetISpanZ(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.IDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取Q路数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetQSpanZ(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.QDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取I路数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetISpanZ(long startIndex, long length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.IDataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取Q路数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetQSpanZ(long startIndex, long length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.QDataPtr + startIndex, length);
        }






        /// <summary>
        /// Copies the contents of this span into a new array.  This heap
        /// allocates, so should generally be avoided, however it is sometimes
        /// necessary to bridge the gap with APIs written in terms of arrays.
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T[] ToArray()
        {
            if (this.LongLength == 0)
            {
#if NET4_0
                return ArrayEx.Empty<T>();
#else
                return Array.Empty<T>();
#endif
            }

            var destination = new T[this.LongLength * 2];
            long index = 0;
            for (long i = 0; i < this.LongLength; i++)
            {
                destination[index++] = this.IDataPtr[i];
                destination[index++] = this.QDataPtr[i];
            };
            return destination;
        }

        /// <summary>
        /// Copies the contents of this span into a new array.  This heap
        /// allocates, so should generally be avoided, however it is sometimes
        /// necessary to bridge the gap with APIs written in terms of arrays.
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T[] IToArray()
        {
            if (this.LongLength == 0)
            {
#if NET4_0
                return ArrayEx.Empty<T>();
#else
                return Array.Empty<T>();
#endif
            }

            var destination = new T[this.LongLength];
            fixed (T* ptr = destination)
            {
                NativeMemory.Copy(this.IDataPtr, ptr, new nuint((ulong)(this.LongLength * sizeof(T))));
            }
            return destination;
        }

        /// <summary>
        /// Copies the contents of this span into a new array.  This heap
        /// allocates, so should generally be avoided, however it is sometimes
        /// necessary to bridge the gap with APIs written in terms of arrays.
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T[] QToArray()
        {
            if (this.LongLength == 0)
            {
#if NET4_0
                return ArrayEx.Empty<T>();
#else
                return Array.Empty<T>();
#endif
            }

            var destination = new T[this.LongLength];
            fixed (T* ptr = destination)
            {
                NativeMemory.Copy(this.QDataPtr, ptr, new nuint((ulong)(this.LongLength * sizeof(T))));
            }
            return destination;
        }

        /// <summary>
        /// 将数据拷贝到列表中
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public List<T> ToList()
        {
            if (this.LongLength == 0)
            {
                return new List<T>();
            }

            T* iPtr = this.IDataPtr;
            T* qPtr = this.QDataPtr;
            var destination = new List<T>(this.Length * 2);
            for (int i = 0; i < destination.Count; i++)
            {
                destination.Add(*iPtr++);
                destination.Add(*qPtr++);
            }

            return destination;
        }

        /// <summary>
        /// 将数据拷贝到列表中
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Complex[] ToComplexArray()
        {
            if (this.LongLength == 0)
            {
                return new Complex[0];
            }

            PrimitiveDataTypes dataType = TypeEx.GetPrimitiveDataType(*this.IDataPtr);
            var destination = new Complex[this.LongLength];
            switch (dataType)
            {
                case PrimitiveDataTypes.SByte:
                    byte* byteIPtr = (byte*)this.IDataPtr;
                    byte* byteQPtr = (byte*)this.QDataPtr;
                    for (long i = 0; i < destination.LongLength; i++)
                    {
                        destination[i] = new Complex(*byteIPtr++, *byteQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Int16:
                    short* shortIPtr = (short*)this.IDataPtr;
                    short* shortQPtr = (short*)this.QDataPtr;
                    for (long i = 0; i < destination.LongLength; i++)
                    {
                        destination[i] = new Complex(*shortIPtr++, *shortQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Int32:
                    int* intIPtr = (int*)this.IDataPtr;
                    int* intQPtr = (int*)this.QDataPtr;
                    for (long i = 0; i < destination.LongLength; i++)
                    {
                        destination[i] = new Complex(*intIPtr++, *intQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Float:
                    float* floatIPtr = (float*)this.IDataPtr;
                    float* floatQPtr = (float*)this.QDataPtr;
                    for (long i = 0; i < destination.LongLength; i++)
                    {
                        destination[i] = new Complex(*floatIPtr++, *floatQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Double:
                    double* doubleIPtr = (double*)this.IDataPtr;
                    double* doubleQPtr = (double*)this.QDataPtr;
                    for (long i = 0; i < destination.LongLength; i++)
                    {
                        destination[i] = new Complex(*doubleIPtr++, *doubleQPtr++);
                    }
                    break;
                default:
                    throw new NotImplementedException(dataType.ToString());
            }

            return destination;
        }

        /// <summary>
        /// 转换为LocalIQSpanZ表示的当前内存引用
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalIQSpanZ<T> ToLocalIQSpanZ()
        {
            return new LocalIQSpanZ<T>(this);
        }

        /// <summary>
        /// 将当前类型强制转换为目标的类型
        /// </summary>
        /// <typeparam name="TResult">目标类型</typeparam>
        /// <returns>目标类型SpanZ</returns>
        public IQSpanZ<TResult> Cast<TResult>() where TResult : struct
        {
            return new IQSpanZ<TResult>(this.IDataPtr, this.QDataPtr, this.LongLength * sizeof(T) / sizeof(TResult));
        }




        /// <summary>
        /// Returns true if left and right point at the same memory and have the same length.  Note that
        /// this does *not* check to see if the *contents* are equal.
        /// </summary>
        public static bool operator ==(IQSpanZ<T> left, IQSpanZ<T> right)
        {
            if (left.Length != right.Length)
            {
                return false;
            }

            if (left.IDataPtr != right.IDataPtr)
            {
                return false;
            }


            if (left.QDataPtr != right.QDataPtr)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Returns false if left and right point at the same memory and have the same length.  Note that
        /// this does *not* check to see if the *contents* are equal.
        /// </summary>
        public static bool operator !=(IQSpanZ<T> left, IQSpanZ<T> right)
        {
            return !(left == right);
        }

        /// <summary>
        /// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
        /// </summary>
        public static implicit operator IQSpanZ<T>(IQUnmanagedMemoryPointer<T> pointer)
        {
            return pointer.GetIQSpanZ();
        }



        /// <summary>
        /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
        /// </summary>
        /// <param name="obj">比较参数</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">Always thrown by this method.</exception>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override bool Equals(object obj)
        {
            throw new NotSupportedException("NotSupported_CannotCallEqualsOnIQSpan");
        }

        /// <summary>
        /// This method is not supported as spans cannot be boxed.
        /// </summary>
        /// <exception cref="NotSupportedException">
        /// Always thrown by this method.
        /// </exception>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override int GetHashCode()
        {
            throw new NotSupportedException("NotSupported_CannotCallGetHashCodeOnIQSpan");
        }






        /// <summary>
        /// Copies the contents of this span into destination span. If the source
        /// and destinations overlap, this method behaves as if the original values in
        /// a temporary location before the destination is overwritten.
        /// </summary>
        /// <param name="sourceIndex">数据源起始位置</param>
        /// <param name="destination">The span to copy items into.</param>
        /// <param name="destinationIndex">目标数据起始位置</param>
        /// <param name="count">数据个数</param>
        /// <exception cref="ArgumentException">
        /// Thrown when the destination Span is shorter than the source Span.
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(int sourceIndex, Complex[] destination, int destinationIndex, int count)
        {
            if (destinationIndex < 0 || destinationIndex >= destination.Length)
            {
                throw new ArgumentOutOfRangeException("起始索引越界", $"destinationIndex:{destinationIndex},destinationIndex:{destinationIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            if (count > this.Length)
            {
                throw new ArgumentOutOfRangeException("源数据长度不足", $"destinationIndex:{destinationIndex},destinationIndex:{destinationIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            PrimitiveDataTypes dataType = TypeEx.GetPrimitiveDataType(*this.IDataPtr);
            long destIndex = destinationIndex;
            switch (dataType)
            {
                case PrimitiveDataTypes.SByte:
                    byte* byteIPtr = (byte*)(this.IDataPtr + sourceIndex);
                    byte* byteQPtr = (byte*)(this.QDataPtr + sourceIndex);
                    for (long i = 0; i < count; i++)
                    {
                        destination[destIndex] = new Complex(*byteIPtr++, *byteQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Int16:
                    short* shortIPtr = (short*)(this.IDataPtr + sourceIndex);
                    short* shortQPtr = (short*)(this.QDataPtr + sourceIndex);
                    for (long i = 0; i < count; i++)
                    {
                        destination[destIndex] = new Complex(*shortIPtr++, *shortQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Int32:
                    int* intIPtr = (int*)(this.IDataPtr + sourceIndex);
                    int* intQPtr = (int*)(this.QDataPtr + sourceIndex);
                    for (long i = 0; i < count; i++)
                    {
                        destination[destIndex] = new Complex(*intIPtr++, *intQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Float:
                    float* floatIPtr = (float*)(this.IDataPtr + sourceIndex);
                    float* floatQPtr = (float*)(this.QDataPtr + sourceIndex);
                    for (long i = 0; i < count; i++)
                    {
                        destination[destIndex] = new Complex(*floatIPtr++, *floatQPtr++);
                    }
                    break;
                case PrimitiveDataTypes.Double:
                    double* doubleIPtr = (double*)(this.IDataPtr + sourceIndex);
                    double* doubleQPtr = (double*)(this.QDataPtr + sourceIndex);
                    for (long i = 0; i < count; i++)
                    {
                        destination[destIndex] = new Complex(*doubleIPtr++, *doubleQPtr++);
                    }
                    break;
                default:
                    throw new NotImplementedException(dataType.ToString());
            }
        }

        /// <summary>
        /// Copies the contents of this span into destination span. If the source
        /// and destinations overlap, this method behaves as if the original values in
        /// a temporary location before the destination is overwritten.
        /// </summary>
        /// <param name="destination">The span to copy items into.</param>
        /// <exception cref="ArgumentException">
        /// Thrown when the destination Span is shorter than the source Span.
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(IQSpanZ<T> destination)
        {
            if (this.LongLength > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException("目标长度不足");
            }

            nuint byteLength = new nuint((ulong)(this.LongLength * sizeof(T)));
            NativeMemory.Copy(this.IDataPtr, destination.IDataPtr, byteLength);
            NativeMemory.Copy(this.QDataPtr, destination.QDataPtr, byteLength);
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,作参数检查
        /// </summary>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(int soucrceStartIndex, IQSpanZ<T> destination, int destinationStartIndex, int count)
        {
            if (soucrceStartIndex < 0 || soucrceStartIndex >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(soucrceStartIndex), "复制的源数据起始位置超出了当前数据容量范围", $"复制的源数据起始位置超出了当前数据容量范围,soucrceStartIndex:{soucrceStartIndex},destinationStartIndex:{destinationStartIndex},length:{count},当前数据长度:{this.LongLength}");
            }

            long soucrceStartIndexL = soucrceStartIndex;
            long countL = count;
            if (soucrceStartIndexL + countL > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了当前数据容量", $"复制的数据长度超出了当前数据容量,soucrceStartIndex:{soucrceStartIndex},destinationStartIndex:{destinationStartIndex},length:{count},当前数据长度:{this.LongLength}");
            }

            if (destination == null)
            {
                throw new ArgumentOutOfRangeException(nameof(destination));
            }

            long destinationStartIndexL = destinationStartIndex;
            if (destinationStartIndexL < 0 || destinationStartIndexL >= destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationStartIndex), $"复制的目标数据起始位置超出了当前数据容量范围,start:{destinationStartIndex},destinationStartIndex:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            if (destinationStartIndex + countL > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), $"复制的数据长度超出了目标数据容量,start:{destinationStartIndex},destinationStartIndex:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            nuint byteLength = new nuint((ulong)(countL * sizeof(T)));
            NativeMemory.Copy(this.IDataPtr + soucrceStartIndex, destination.IDataPtr + destinationStartIndex, byteLength);
            NativeMemory.Copy(this.QDataPtr + soucrceStartIndex, destination.QDataPtr + destinationStartIndex, byteLength);
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,作参数检查
        /// </summary>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(long soucrceStartIndex, IQSpanZ<T> destination, long destinationStartIndex, long count)
        {
            if (soucrceStartIndex < 0 || soucrceStartIndex >= this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(soucrceStartIndex), "复制的源数据起始位置超出了当前数据容量范围", $"复制的源数据起始位置超出了当前数据容量范围,soucrceStartIndex:{soucrceStartIndex},destinationStartIndex:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            if (soucrceStartIndex + count > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了当前数据容量", $"复制的数据长度超出了当前数据容量,soucrceStartIndex:{soucrceStartIndex},destinationStartIndex:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            if (destination == null)
            {
                throw new ArgumentOutOfRangeException(nameof(destination));
            }

            if (destinationStartIndex < 0 || destinationStartIndex >= destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationStartIndex), $"复制的目标数据起始位置超出了当前数据容量范围,start:{destinationStartIndex},destinationStartIndex:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            if (destinationStartIndex + count > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), $"复制的数据长度超出了目标数据容量,start:{destinationStartIndex},count:{count},当前数据长度:{this.LongLength}");
            }

            nuint byteLength = new nuint((ulong)(count * sizeof(T)));
            NativeMemory.Copy(this.IDataPtr + soucrceStartIndex, destination.IDataPtr + destinationStartIndex, byteLength);
            NativeMemory.Copy(this.QDataPtr + soucrceStartIndex, destination.QDataPtr + destinationStartIndex, byteLength);
        }





        /// <summary>
        /// 将源数据复制到目标数据中,不作参数检查
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="destination">目标数据</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(IQSpanZ<T> source, IQSpanZ<T> destination)
        {
            nuint byteLength = new nuint((ulong)(source.LongLength * sizeof(T)));
            NativeMemory.Copy(source.IDataPtr, destination.IDataPtr, byteLength);
            NativeMemory.Copy(source.QDataPtr, destination.QDataPtr, byteLength);
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,不作参数检查
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(IQSpanZ<T> source, int soucrceStartIndex, IQSpanZ<T> destination, int destinationStartIndex, int count)
        {
            nuint byteLength = new nuint((ulong)count * (ulong)sizeof(T));
            NativeMemory.Copy(source.IDataPtr + soucrceStartIndex, destination.IDataPtr + destinationStartIndex, byteLength);
            NativeMemory.Copy(source.QDataPtr + soucrceStartIndex, destination.QDataPtr + destinationStartIndex, byteLength);
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,不作参数检查
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(IQSpanZ<T> source, long soucrceStartIndex, IQSpanZ<T> destination, long destinationStartIndex, long count)
        {
            nuint byteLength = new nuint((ulong)(count * sizeof(T)));
            NativeMemory.Copy(source.IDataPtr + soucrceStartIndex, destination.IDataPtr + destinationStartIndex, byteLength);
            NativeMemory.Copy(source.QDataPtr + soucrceStartIndex, destination.QDataPtr + destinationStartIndex, byteLength);
        }






        /// <summary>
        /// Copies the contents of this span into destination span. If the source
        /// and destinations overlap, this method behaves as if the original values in
        /// a temporary location before the destination is overwritten.
        /// </summary>
        /// <param name="destination">The span to copy items into.</param>
        /// <returns>If the destination span is shorter than the source span, this method
        /// return false and no data is written to the destination.</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public bool TryCopyTo(IQSpanZ<T> destination)
        {
            if (this.LongLength > destination.LongLength)
            {
                return false;
            }

            nuint byteLength = new nuint((ulong)this.LongLength * (ulong)sizeof(T));
            NativeMemory.Copy(this.IDataPtr, destination.IDataPtr, byteLength);
            NativeMemory.Copy(this.QDataPtr, destination.QDataPtr, byteLength);
            return true;
        }







        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>String</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < this.Length; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                sb.Append(this.IDataPtr[i]);
                sb.Append(',');
                sb.Append(this.QDataPtr[i]);
            }

            return sb.ToString();
        }

    }



}
